package com.xxjd.config;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

import java.beans.Introspector;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义包（basePackPath="com.bdsoft"）BeanName生成策略, 解决不同包下同名类问题
 * 参考博客： https://blog.csdn.net/brave_heart4pzj/article/details/106527849
 */
public class SpringBeanNameGenerator extends AnnotationBeanNameGenerator {
    // 需要处理的文件路径
    private final Map<String, BeanNameStrategy> modulePackPath = new HashMap<>();

    private final String basePackPath = "com.xxjd";

    private void init() {
        modulePackPath.put("com.bdsoft.pia", BeanNameStrategy.MODULE_NAME_STRATEGY);
        modulePackPath.put("com.bdsoft.ca", BeanNameStrategy.SPRING_DEFAULT);
    }

    /**
     * bean生辰策略
     *
     * @param definition
     * @return
     */
    @Override
    protected String buildDefaultBeanName(BeanDefinition definition) {
        if (modulePackPath.size() == 0) init();
        // 获取文件全路径
        String beanClassName = definition.getBeanClassName();
        // 为空的时候抛出异常信息
        Assert.state(beanClassName != null, "No bean class name set");
        // 为自定义包下的代码进行生辰bean策略修改
        if (beanClassName.startsWith(basePackPath)) {
            return buildBeanName(definition);
        } else { // 默认生辰策略
            return super.buildDefaultBeanName(definition);
//            // 获取文件名（去掉后缀的）
//            String shortClassName = ClassUtils.getShortName(beanClassName);
//            // 如果首字母和第二个字母都是大写，这直接使用类名作为bean名称 默认是首字母转换成小写，作为bean名称
//            return Introspector.decapitalize(shortClassName);
        }


    }


    /**
     * 以class路径，作为bean名称
     *
     * @param definition
     * @return
     */
    private String buildBeanName(BeanDefinition definition) {
        final String beanClassName = definition.getBeanClassName();
        Assert.state(beanClassName != null, "No bean class name set");
        for (Map.Entry<String, BeanNameStrategy> entry : modulePackPath.entrySet()) {
            if (beanClassName.startsWith(entry.getKey())) {
                return doGetUniqueBeanName(beanClassName, entry.getValue());
            }
        }
        return beanClassName;
    }

    /**
     * 以class
     *
     * @param beanClassName 类名
     * @return
     */
    private String doGetUniqueBeanName(String beanClassName, BeanNameStrategy beanNameStrategy) {
        switch (beanNameStrategy) {
            case MODULE_NAME_STRATEGY: {
                return getModuleBeanName(beanClassName);
            }
            case PACKAGE_PATH_NAME_STRATEGY: {
                // class路径作为bean name
                return beanClassName;
            }
            case SPRING_DEFAULT: {
                // 获取文件名（去掉后缀的）
                String shortClassName = ClassUtils.getShortName(beanClassName);
                // 如果首字母和第二个字母都是大写，这直接使用类名作为bean名称 默认是首字母转换成小写，作为bean名称
                return Introspector.decapitalize(shortClassName);
            }
        }
        return beanClassName;
    }

    private String getModuleBeanName(String beanClassName) {
        String result = beanClassName;
        String[] strArr = beanClassName.split("\\.");
        final int length = strArr.length;
        if (length > 0) {
            String fileName = strArr[length - 1];
            String moduleName = "";
            if (length > 2) {
                moduleName = strArr[2];
            }
            if (moduleName != null && moduleName.length() > 0) {
                result = moduleName + fileName;
            }
        }

        return convertBeanName(result);
    }

    private String convertBeanName(String str) {
        if (str == null) {
            return null;
        }
        if (str.length() < 3) {
            return str;
        }
        final char firstChar = str.charAt(0);
        final char secondChar = str.charAt(1);
        if (Character.isUpperCase(firstChar) && Character.isUpperCase(secondChar)) {
            return str;
        }
        return Character.toLowerCase(firstChar) + str.substring(1);
    }

    /**
     * 定义spring bean命名策略
     * MODULE_Name_Strategy： 包不同，允许同名java文件使用默认bean注解（待完善）
     * MODULE_Name_Strategy： 模块不同，允许同名java文件使用默认bean注解
     * SPRING_DEFAULT_Name_Strategy： 使用默认bean定义名称
     */
    enum BeanNameStrategy {
        //模块名称+java文件名
        MODULE_NAME_STRATEGY,
        //包名称+java文件名
        PACKAGE_PATH_NAME_STRATEGY,
        // 默认文件名
        SPRING_DEFAULT
    }
}
